home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun4.md / machTrap.s < prev    next >
Text File  |  1993-01-06  |  55KB  |  1,689 lines

  1. /*
  2.  * machTrap.s --
  3.  *
  4.  *    Traps for sun4.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. .seg    "data"
  17. .asciz    "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun4.md/machTrap.s,v 9.15 93/01/06 20:09:19 mgbaker Exp $ SPRITE (Berkeley)"
  18. .align    8
  19. .seg    "text"
  20.  
  21. #include "user/proc.h"
  22. #include "machConst.h"
  23. #include "machAsmDefs.h"
  24.  
  25. .align    8
  26. .seg    "text"
  27.  
  28. /*
  29.  * ----------------------------------------------------------------------
  30.  *
  31.  * MachTrap --
  32.  *
  33.  *    All traps except window overflow and window underflow go through
  34.  *    this trap handler.  This handler is used to save the appropriate
  35.  *    state, set up the kernel stack, and then jump to the correct
  36.  *    handler depending on the type of trap.  The handler assumes that
  37.  *    we have saved the trap %psr into %CUR_PSR_REG before we get here (as
  38.  *    an instruction in the vector table that made us branch here).
  39.  *
  40.  *    Window overflow and underflow jump directly from the vector table
  41.  *    to their handlers, since in the most common cases they do not need
  42.  *    to save state and they should be as fast as possible.
  43.  *
  44.  *    The scheme of things:
  45.  *
  46.  *    1) Check to see if we're in an invalid window.  If so, deal first with
  47.  *    window overflow.
  48.  *    2) Now that it's safe to overwrite our out registers, update the stack
  49.  *    pointer.  If coming from user mode, this means pulling the kernel
  50.  *    stack pointer out of the state structure and adding the appropriate
  51.  *    amount.  Otherwise, it means just means adding the appropriate amount to
  52.  *    our %fp.
  53.  *    3) Save the rest of the trap state (globals) to the stack.  Note that
  54.  *    although locals and ins contain trap state (ins are our caller's outs
  55.  *    which we shouldn't mess up, and the psr and other state registers are
  56.  *    in our locals) we need not save them explicitly, since they will be
  57.  *    saved as a part of the normal window overflow and underflow.  There
  58.  *    are exceptions to this, such as context switching or debugger traps,
  59.  *    where we must explicitly save the window to the stack, but the
  60.  *    exceptions must take care of this for themselves.
  61.  *    4) Re-enable traps and disable interrupts.  Traps must be disabled
  62.  *    so that if we get another window overflow or underflow,
  63.  *    we'll be able to deal with it.
  64.  *    5) Figure out what handler to call and call it.
  65.  *
  66.  *    The handler must call our return-from-trap post-amble, rather than
  67.  *    return here.
  68.  *
  69.  *    If a window underflow or overflow trap discovers that it must do
  70.  *    something tricky, such as call Vm_PageIn, that requires turning
  71.  *    on traps and interrupts, then it will call MachTrap to save state
  72.  *    for it.  This is why there are entries in MachTrap for window
  73.  *    overflow and underflow.  These are the entries to take care of the
  74.  *    "slow trap" overflows and underflows.
  75.  *
  76.  * Results:
  77.  *    None.
  78.  *
  79.  * Side effects:
  80.  *    We make space on our kernel stack to save this trap window.
  81.  *    If it is a user process entering the kernel, then we make its trapRegs
  82.  *    field point to this save-window area on the kernel stack.
  83.  *
  84.  * ----------------------------------------------------------------------
  85.  */
  86. .global    _MachTrap
  87. _MachTrap:
  88.     /*
  89.      * Save the state registers.  This is safe, since we're saving them
  90.      * to local registers and we can do this even if we've entered
  91.      * into an invalid window.
  92.      * In the vector table that jumps here, we have already saved
  93.      * the %psr into %CUR_PSR_REG.  The trap instruction itself saved
  94.      * the trap pc and next pc into local registers %CUR_PC_REG and
  95.      * %NEXT_PC_REG.  This means we must save only the %tbr and the %y
  96.      * registers.
  97.      */
  98.     mov    %tbr, %CUR_TBR_REG
  99.     mov    %y, %CUR_Y_REG
  100.     /*
  101.      * Are we in an invalid window?
  102.      */
  103.     MACH_INVALID_WINDOW_TEST()
  104.     be    WindowOkay
  105.     nop
  106.     /*
  107.      * Deal with window overflow - put return addr in SAFE_TEMP since
  108.      * the overflow handler will look for the return address there..
  109.      * It is okay to do this, even if we got here after due to a slow
  110.      * overflow trap due to special action needed, because if we did that,
  111.      * then we've already taken care of the overflow problem and so we
  112.      * won't get it here and so we won't be overwriting the return address
  113.      * in SAFE_TEMP.
  114.      */
  115.     set    MachWindowOverflow, %VOL_TEMP1
  116.     jmpl    %VOL_TEMP1, %SAFE_TEMP
  117.     nop
  118. WindowOkay:
  119.     /*
  120.      * Now that we know our out registers are safe to use, since we're
  121.      * in a valid window, update our stack  pointer.
  122.      * If coming from user mode, I need to get kernel sp from
  123.      * state structure.  If we came from kernel
  124.      * mode, just subtract a stack frame from the current frame pointer and
  125.      * continue. To see if we came from user mode, we look at the
  126.      * previous state bit (PS) in the processor state register.
  127.      * I set up the stack pointer in the delay slot of the branch if I came
  128.      * from kernel mode, so it's as fast as possible.  I annul the
  129.      * instruction if it turns out to be a user stack.
  130.      * We must give the stack a full state frame so that C routines
  131.      * we call will have space to store their arguments.  (System calls,
  132.      * for example!)
  133.      *
  134.      * NOTE: The amount we bump up the stack by here must
  135.      * agree with the debugger stack test in the window underflow routine,
  136.      * so that we don't trash our stack when returning from the
  137.      * debugger!!!!!
  138.      */
  139.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0         /* previous state? */
  140.         bne,a   DoneWithUserStuff             /* was kernel mode */
  141.         add     %fp, -MACH_SAVED_STATE_FRAME, %sp     /* set kernel sp */
  142.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP2, %VOL_TEMP1)    /* into %VOL_TEMP2 */
  143.         add     %VOL_TEMP2, MACH_KSP_OFFSET, %VOL_TEMP1 /* &(machPtr->ksp) */
  144.         ld      [%VOL_TEMP1], %sp             /* machPtr->ksp */
  145.     set    (MACH_KERN_STACK_SIZE - MACH_SAVED_STATE_FRAME), %VOL_TEMP1
  146.         add     %sp, %VOL_TEMP1, %sp 
  147.     /*
  148.      * Since we came from user mode, set the trapRegs field of the
  149.      * current state structure to the value of our new kernel sp,
  150.      * since the trap regs are saved on top of the stack.
  151.      */
  152.     add    %VOL_TEMP2, MACH_TRAP_REGS_OFFSET, %VOL_TEMP2
  153.     st    %sp, [%VOL_TEMP2]
  154.  
  155. DoneWithUserStuff:
  156.     /* Test stack alignment here?? */
  157.  
  158.     /*
  159.      * This only saves the globals to the stack.  The locals
  160.      * and ins make it there through normal overflow and underflow.
  161.      *
  162.      * NOTE that we cannot trash %g1 even after saving the global
  163.      * registers, since that is the register that contains the system
  164.      * call number for system call traps!
  165.      */
  166.     MACH_SAVE_GLOBAL_STATE()
  167.  
  168.     /* traps on, maskable interrupts off */
  169.     MACH_SR_HIGHPRIO()
  170.  
  171.     /*
  172.      * It is tedious to do all these serial comparisons against the
  173.      * trap type, so this should be changed to a jump table.  It's this
  174.      * way right now because I'm working on other things and this is
  175.      * easy for debugging.
  176.      */
  177.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %VOL_TEMP1 /* get trap */
  178.  
  179.     cmp    %VOL_TEMP1, MACH_LEVEL0_INT
  180.     bl    NotAnInterrupt
  181.     nop
  182.     cmp    %VOL_TEMP1, MACH_LEVEL15_INT
  183.     bgu    NotAnInterrupt
  184.     nop
  185.     /*
  186.      * It's an interrupt.
  187.      */
  188.     b    MachHandleInterrupt
  189.     nop
  190.  
  191. NotAnInterrupt:
  192.  
  193.     cmp    %VOL_TEMP1, MACH_TRAP_SYSCALL        /* system call */
  194.     be    MachSyscallTrap
  195.     nop
  196.  
  197.     cmp    %VOL_TEMP1, MACH_INSTR_ACCESS        /* instruction fault */
  198.     be    MachHandlePageFault
  199.     nop
  200.  
  201.     cmp    %VOL_TEMP1, MACH_DATA_ACCESS        /* data fault */
  202.     be    MachHandlePageFault
  203.     nop
  204.  
  205.     cmp    %VOL_TEMP1, MACH_TRAP_SIG_RETURN    /* ret from handler */
  206.     be    _MachReturnFromSignal
  207.     nop
  208.  
  209.     cmp    %VOL_TEMP1, MACH_TRAP_FLUSH_WINDOWS    /* flush window trap */
  210.     be    MachFlushWindowsToStackTrap
  211.     nop
  212.  
  213.     cmp    %VOL_TEMP1, MACH_TRAP_UNIX_SYSCALL    /* unix syscall */
  214.     be    MachUnixSyscallTrap
  215.     nop
  216.  
  217.     cmp    %VOL_TEMP1, MACH_TRAP_INSTR_2        /* Dynamic linking  */
  218.     be    MachLinkTrap
  219.     nop
  220.  
  221.     /*
  222.      * These next few are handled by C routines, and we want them to
  223.      * return to MachReturnFromTrap, so set that address as the return pc.
  224.      */
  225.     cmp    %VOL_TEMP1, MACH_ILLEGAL_INSTR        /* illegal instr */
  226.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  227.     mov    %VOL_TEMP1, %o0
  228.     mov    %CUR_PC_REG, %o1
  229.     mov    %CUR_PSR_REG, %o2
  230.     be    _MachHandleTrap        /* C routine */
  231.     nop
  232.  
  233.     cmp    %VOL_TEMP1, MACH_PRIV_INSTR        /* privileged instr */
  234.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  235.     mov    %VOL_TEMP1, %o0
  236.     mov    %CUR_PC_REG, %o1
  237.     mov    %CUR_PSR_REG, %o2
  238.     be    _MachHandleTrap        /* C routine */
  239.     nop
  240.  
  241.     cmp    %VOL_TEMP1, MACH_MEM_ADDR_ALIGN        /* addr not aligned */
  242.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  243.     mov    %VOL_TEMP1, %o0
  244.     mov    %CUR_PC_REG, %o1
  245.     mov    %CUR_PSR_REG, %o2
  246.     be    _MachHandleTrap        /* C routine */
  247.     nop
  248.  
  249.     cmp    %VOL_TEMP1, MACH_TAG_OVERFLOW        /* tagged instr ovfl */
  250.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  251.     mov    %VOL_TEMP1, %o0
  252.     mov    %CUR_PC_REG, %o1
  253.     mov    %CUR_PSR_REG, %o2
  254.     be    _MachHandleTrap        /* C routine */
  255.     nop
  256.  
  257.     cmp    %VOL_TEMP1, MACH_FP_EXCEP        /* fp unit badness */
  258.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  259.     mov    %VOL_TEMP1, %o0
  260.     mov    %CUR_PC_REG, %o1
  261.     mov    %CUR_PSR_REG, %o2
  262.     be    _MachHandleTrap        /* C routine */
  263.     nop
  264.  
  265.     cmp    %VOL_TEMP1, MACH_FP_DISABLED        /* fp unit disabled */
  266.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  267.     mov    %VOL_TEMP1, %o0
  268.     mov    %CUR_PC_REG, %o1
  269.     mov    %CUR_PSR_REG, %o2
  270.     be    _MachHandleTrap        /* C routine */
  271.     nop
  272.  
  273.     /*
  274.      * We never get here directly from the window overflow trap.
  275.      * Instead, what this means is that after handling a window
  276.      * overflow trap, on the way out we had to deal with a special
  277.      * user action.  Because we don't save state, etc, on a regular
  278.      * window overflow, we've executed the above code to save the
  279.      * state for us.  Now we just want to go back and deal with the
  280.      * special overflow.
  281.      */
  282.     cmp    %VOL_TEMP1, MACH_WINDOW_OVERFLOW    /* weird overflow */
  283.     be    MachReturnToOverflowWithSavedState
  284.     nop
  285.  
  286.     cmp    %VOL_TEMP1, MACH_WINDOW_UNDERFLOW    /* weird underflow */
  287.     be    MachReturnToUnderflowWithSavedState
  288.     nop
  289.  
  290.     cmp    %VOL_TEMP1, MACH_TRAP_DEBUGGER        /* enter debugger */
  291.     be    _MachHandleDebugTrap
  292.     nop
  293.  
  294.     b    _MachHandleDebugTrap        /* all  others to debugger */
  295.     nop
  296.  
  297.  
  298. /*
  299.  * ----------------------------------------------------------------------
  300.  *
  301.  * MachReturnFromTrap --
  302.  *
  303.  *    Go through the inverse of MachTrap.  The trap handlers that MachTrap
  304.  *    called return to here rather than MachTrap.
  305.  *
  306.  *    The scheme of things:
  307.  *
  308.  *    1) Determine if we are returning to user mode.  If so, then we must
  309.  *    check the specialHandling flag.  If it is set, then we must call
  310.  *    MachUserAction.
  311.  *    2) If we called MachUserAction, then we must check its return value
  312.  *    to see if we need to deal with any signals.  If we do, then
  313.  *    we call MachHandleSignal().  It returns to user mode itself via
  314.  *    a rett instruction, so we don't come back here until the
  315.  *    return-from-signal trap that the user ends up executing to return to
  316.  *    the kernel from a signal.
  317.  *    3) For both returns to user mode and returns to kernel mode, we
  318.  *    must next check if we would return to an invalid window.  If so,
  319.  *    we must make it valid or we will get a watchdog reset.  We may
  320.  *    call the window underflow routine to do this.  But, if we are
  321.  *    returning to user mode, we must check to make sure the user stack
  322.  *    is resident, since the underflow routine can't get any page faults.
  323.  *    If the user stack isn't resident, we page it in.
  324.  *    4) Finally, we disable traps again (or the rett instruction will
  325.  *    give us a watchdog reset), restore the global registers, restore
  326.  *    the %tbr, %y registers, restore the %psr to the trap psr, and rett
  327.  *    (return from trap) to the saved trap pc and next pc.
  328.  *
  329.  * Results:
  330.  *    None.
  331.  *
  332.  * Side effects:
  333.  *    We jump back to where we came from.  If we came from a system call
  334.  *    or certain other traps, we'll actually return to where we came from
  335.  *    plus 8, or else we would re-execute the system call instruction.
  336.  *    The addition of 8 was done by the individual handlers that know
  337.  *    whether or not they would need to do this.
  338.  *
  339.  *    If a user process has a bad stack pointer, we will kill it here and
  340.  *    print out a message.
  341.  *
  342.  * ----------------------------------------------------------------------
  343.  */
  344. .global    _MachReturnFromTrap
  345. _MachReturnFromTrap:
  346.     /* Are we a user or kernel process? */
  347.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  348.     bne    NormalReturn
  349.     nop
  350.     /* Do we need to take a special action? Check special handling flag. */
  351.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)
  352.     sethi    %hi(_machSpecialHandlingOffset), %VOL_TEMP2
  353.     ld    [%VOL_TEMP2 + %lo(_machSpecialHandlingOffset)], %VOL_TEMP2
  354.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  355.     ld    [%VOL_TEMP1], %VOL_TEMP1
  356.     tst    %VOL_TEMP1
  357.     be    NormalReturn
  358.     nop
  359.     call    _MachUserAction
  360.     nop
  361.     /* Check if we must handle a signal */
  362.     tst    %RETURN_VAL_REG
  363.     be    NormalReturn
  364.     nop
  365.     cmp    %RETURN_VAL_REG, 2
  366.     be    DoUnixSignal
  367.     nop
  368.     /*
  369.      * We must handle a signal.  Call the leaf routine MachSetupSignal.
  370.      * It does its own return from trap, so we don't come back here when
  371.      * it's done!
  372.      */
  373.     call    _MachHandleSignal
  374.     nop
  375. DoUnixSignal:
  376.     MACH_RESTORE_WINDOW_FROM_STACK()
  377.     nop
  378.     sub    %fp, 0x8f0, %fp
  379.     nop
  380. NormalReturn:
  381.     MACH_UNDERFLOW_TEST()
  382.     be    UnderflowOkay
  383.     nop
  384.     /*
  385.      * Make sure stack is resident.  We don't want to get a page
  386.      * fault in the underflow routine, because it moves into the window
  387.      * to restore and so its calls to Vm code would move into this
  388.      * window and overwrite it!  First check if it's a user process, since
  389.      * that should be the only case where the stack isn't resident.
  390.      */
  391.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  392.     bne    CallUnderflow
  393.     nop
  394.     /*
  395.      * It's a user process, so check residence and protection fields of pte.
  396.      * Before anything we check stack alignment.
  397.      */
  398.     andcc    %fp, 0x7, %g0
  399.     bne    KillUserProc
  400.     nop
  401.     MACH_CHECK_FOR_FAULT(%fp, %VOL_TEMP1)
  402.     be    CheckNextFault
  403.     nop
  404.     /*
  405.      * Call VM Stuff with the %fp which will be stack pointer in
  406.      * the window we restore.
  407.      */
  408.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  409.     mov    %fp, %o0
  410.     clr    %o1        /* also check for protection????? */
  411.     call    _Vm_PageIn, 2
  412.     nop
  413.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  414.     tst    %RETURN_VAL_REG
  415.     bne    KillUserProc
  416.     nop
  417. CheckNextFault:
  418.     /* Check other extreme of area we'd touch */
  419.     add    %fp, (MACH_SAVED_WINDOW_SIZE - 4), %o0
  420.     MACH_CHECK_FOR_FAULT(%o0, %VOL_TEMP1)
  421.     be    CallUnderflow
  422.     nop
  423.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  424.     clr    %o1
  425.     call    _Vm_PageIn, 2
  426.     nop
  427.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  428.     tst    %RETURN_VAL_REG
  429.     be    CallUnderflow
  430.     nop
  431. KillUserProc:
  432.     /*
  433.      * Kill user process!  Its stack is bad.
  434.      */
  435.     MACH_SR_HIGHPRIO()    /* traps back on for overflow from printf */
  436.     set    _MachReturnFromTrapDeathString, %o0
  437.     call    _printf, 1
  438.     nop
  439.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  440.         sethi    %hi(_machGenFlagsOffset), %o1 
  441.         ld    [%o1 + %lo(_machGenFlagsOffset)], %o1
  442.         add    %o0, %o1, %o1
  443.         ld    [%o1], %o1
  444.         sethi    %hi(_machForeignFlag), %o2
  445.         ld      [%o2 + %lo(_machForeignFlag)], %o2
  446.         andcc   %o1, %o2, %o1            /* Is this a migrated proc? */
  447.         be      DebugIt
  448.         nop
  449.     set    PROC_TERM_DESTROYED, %o0    /* If so, kill it. */
  450.     set    PROC_BAD_STACK, %o1
  451.     clr    %o2
  452.     call    _Proc_ExitInt, 3
  453.     nop
  454. DebugIt:                    /* Else, make it debuggable. */
  455.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  456.     call    _Sig_CheckForKill, 1        /* kill proc if KILL signal */
  457.     nop
  458.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  459.     set    TRUE, %o1            /* debug TRUE */
  460.     set    PROC_TERM_DESTROYED, %o2
  461.     set    PROC_BAD_STACK, %o3
  462.     clr    %o4
  463.     call    _Proc_SuspendProcess, 5
  464.     nop
  465.     ba    DebugIt            /* proc should loop if continued */
  466.     nop
  467.  
  468. CallUnderflow:
  469.     set    MachWindowUnderflow, %VOL_TEMP1
  470.     jmpl    %VOL_TEMP1, %RETURN_ADDR_REG
  471.     nop
  472. UnderflowOkay:
  473.     MACH_DISABLE_TRAPS(%VOL_TEMP1, %VOL_TEMP2)
  474.     MACH_RESTORE_GLOBAL_STATE()
  475.     /* restore y reg */
  476.     mov    %CUR_Y_REG, %y
  477.  
  478.     /* restore tbr reg */
  479.     mov    %CUR_TBR_REG, %tbr
  480.     /* restore psr */
  481.     MACH_RESTORE_PSR()
  482.     jmp    %CUR_PC_REG
  483.     rett    %NEXT_PC_REG
  484.     nop
  485.  
  486. /*
  487.  * ----------------------------------------------------------------------
  488.  *
  489.  * MachHandleWindowOverflowTrap --
  490.  *
  491.  *    Trap entrance to the window overflow handler.  We try to get in and
  492.  *    out of here as quickly as possible in the normal case.  Unlike
  493.  *    most traps, we jump here directly from the trap table, and do not
  494.  *    go through the usual MachTrap preamble.  This means no
  495.  *    state has been saved and we have no stack pointer.  This in turn means
  496.  *    that we cannot turn traps on, since we have no saved state and no place
  497.  *    to save the trap registers. This routine sets up a return
  498.  *    address, calls the overflow handler, restores the psr, and
  499.  *    returns from the trap.  It assumes that the trap psr was stored in
  500.  *    %CUR_PSR_REG before jumping here (in the trap vector table).
  501.  *
  502.  *    When we return to this routine from the actual overflow handling
  503.  *    routine, we check to see if we're returning to user mode.  If we aren't
  504.  *    we can just leave this routine normally.  If we're returning to user
  505.  *    mode, however, we must check for some special cases.  It may be that
  506.  *    the user stack wasn't resident and that we had to save the overflow
  507.  *    window to a special internal buffer rather than the user stack.  If this
  508.  *    is so, we require extra processing.  So we call MachTrap to save state
  509.  *    for us and then call MachReturnFromTrap, which will handle the fact
  510.  *    that the window was saved to an internal buffer.  The effect of all of
  511.  *    this is to turn the overflow trap into a "slow overflow trap" that goes
  512.  *    through the usual trap preamble and postamble.
  513.  *
  514.  * Results:
  515.  *    None.
  516.  *
  517.  * Side effects:
  518.  *    The mach state structure may be modified if this is a user window
  519.  *    and its stack isn't resident, causing us to save the window to
  520.  *    the buffers in the mach state structure.
  521.  *
  522.  * ----------------------------------------------------------------------
  523.  */
  524. .global    MachHandleWindowOverflowTrap
  525. MachHandleWindowOverflowTrap:
  526.     /*
  527.      * Call actual overflow handler.
  528.      */
  529.     set    MachWindowOverflow, %VOL_TEMP1
  530.     jmpl    %VOL_TEMP1, %SAFE_TEMP
  531.     nop
  532.     /*
  533.      * If returning to user mode, check special handling flags here to
  534.      * see if we need to do any fancy processing (due to the user's
  535.      * stack not being resident so we had to save the window to an internal
  536.      * buffer instead).
  537.      */
  538.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0        /* user or kernel? */
  539.         bne     NormalOverflowReturn
  540.         nop
  541.         /* Do we need to take a special action? Check special handling flag. */
  542.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)
  543.         sethi    %hi(_machSpecialHandlingOffset), %VOL_TEMP2
  544.         ld      [%VOL_TEMP2 + %lo(_machSpecialHandlingOffset)], %VOL_TEMP2
  545.         add     %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  546.         ld      [%VOL_TEMP1], %VOL_TEMP1
  547.         tst     %VOL_TEMP1
  548.         be      NormalOverflowReturn
  549.     nop
  550.     /*
  551.      * We need to save state and allocate space on the stack, etc.
  552.      * Run through regular trap preamble to do this.  The trap preamble
  553.      * will then return us to here.  This is all in preparation for
  554.      * calling MachReturnFromTrap, since that will call MachUserAction
  555.      * to deal with the window saved to the internal buffer.
  556.      */
  557.     call    _MachTrap
  558.     nop
  559. MachReturnToOverflowWithSavedState:
  560.     /*
  561.      * Now call trap postamble to restore state and push saved window to
  562.      * the user stack.  MachReturnFromTrap will return to user mode, so
  563.      * we will not come back here after this call!
  564.      */
  565.     call    _MachReturnFromTrap
  566.     nop
  567.  
  568.     /*
  569.      * This was a normal fast window overflow trap, so just return.
  570.      */
  571. NormalOverflowReturn:
  572.     MACH_RESTORE_PSR()
  573.     jmp    %CUR_PC_REG
  574.     rett    %NEXT_PC_REG
  575.     nop
  576.  
  577. /*
  578.  * ----------------------------------------------------------------------
  579.  *
  580.  * MachWindowOverflow --
  581.  *
  582.  *    Window overflow handler.  It's set up so that it can be called from the
  583.  *    fast window overflow trap handler, or it can be called directly from
  584.  *    MachTrap for any trap that causes us to land inside an invalid window.
  585.  *
  586.  *    The window we've trapped into is currently invalid.  We want to
  587.  *    make it valid.  We do this by moving one window further, saving that
  588.  *    window to the stack, marking it as the new invalid window, and then
  589.  *    moving back to the window that we trapped into.  It is then valid
  590.  *    and usable.  Note that we move first to the window to save and then
  591.  *    mark it invalid.  In the other order we would get another overflow
  592.  *    trap, but with traps turned off, which causes a watchdog reset...
  593.  *    Note that %sp should point to the lowest address usable
  594.  *    word in the current stack frame.  %fp is the %sp of the
  595.  *    caller's stack frame, so the first (highest in memory) usable word
  596.  *    of a current stack frame is (%fp - 4).
  597.  *
  598.  *    This code will be called with traps DISABLED, so nothing in this
  599.  *    code is allowed to cause a trap.  This means no procedure calls are
  600.  *    allowed.
  601.  *
  602.  * Results:
  603.  *    Returns to the address %SAFE_TEMP + 8.
  604.  *
  605.  * Side effects:
  606.  *    The window invalid mask changes and a register window is saved.
  607.  *    The mach state structure may change if we need to save this window
  608.  *    into its internal buffers (if it's a user window and the stack isn't
  609.  *    resident).
  610.  *
  611.  * ----------------------------------------------------------------------
  612.  */
  613. .global    MachWindowOverflow
  614. MachWindowOverflow:
  615.     /*
  616.      * We enter inside of an invalid window, so we can't use in registers,
  617.      * out registers or global registers to begin with.
  618.      * We temporarily clear out some globals since we won't be able to
  619.      * use locals in window we move to before saving it.  Using them would
  620.      * mess them up for window's owner.
  621.      */
  622.     mov    %g3, %VOL_TEMP1
  623.     mov    %g4, %VOL_TEMP2
  624.     save                /* move to the window to save */
  625.     MACH_ADVANCE_WIM(%g3, %g4)    /* reset %wim to current window */
  626.     /*
  627.      * If this is a user window, then see if stack space is resident.
  628.      * If it is, go ahead, but if not, then set special handling and
  629.      * save to buffers.  It's fairly dreadful that we must do all this
  630.      * checking here, since this will slow down all the overflow traps.
  631.      */
  632.     set    MACH_MAX_USER_STACK_ADDR, %g3    /* %sp in user space? */
  633.     subcc    %g3, %sp, %g0            /* need sp < highest addr */
  634.     bleu    NotUserStack
  635.     nop
  636.     set    MACH_FIRST_USER_ADDR, %g3    /* need sp >= lowest addr */
  637.     subcc    %sp, %g3, %g0
  638.     bgeu    UserStack
  639.     nop
  640. NotUserStack:
  641.     set    MACH_STACK_BOTTOM, %g3
  642.     subcc    %sp, %g3, %g0            /* need sp >= lowest addr */
  643.     blu    BadStack
  644.     nop
  645.     set    VMMACH_DEV_START_ADDR, %g3    /* need sp < highest addr */
  646.     subcc    %g3, %sp, %g0
  647.     bgu    NormalOverflow
  648.     nop
  649. BadStack:
  650.     /*
  651.      * Assume it was a user process's bad stack pointer.  We can't kill
  652.      * the process here, so just take over the window and the user process
  653.      * will die a terrible death later.  To take over the window, we just
  654.      * return, since we've already advanced the %wim.
  655.      */
  656.     ba    ReturnFromOverflow
  657.     nop
  658. UserStack:
  659.     /*
  660.      * If the stack alignment is bad, we just take over the window and
  661.      * assume the user process will die a horrible death later on.
  662.      */
  663.     andcc    %sp, 0x7, %g0
  664.     bne    ReturnFromOverflow
  665.     nop
  666.  
  667.     /* Would saving window cause a page fault? */
  668.     MACH_CHECK_FOR_FAULT(%sp, %g3)
  669.     bne    SaveToInternalBuffer
  670.     nop
  671.  
  672.     /* check other address extreme */
  673.     add    %sp, (MACH_SAVED_WINDOW_SIZE - 4), %g4
  674.     MACH_CHECK_FOR_FAULT(%g4, %g3)
  675.     be    NormalOverflow
  676.     nop
  677. SaveToInternalBuffer:
  678.     /*
  679.      * The stack wasn't resident, so we must save to an internal buffer
  680.      * and set the special handling flag.
  681.      * We update the saved mask to show that this window had to be saved
  682.      * to the internal buffers.  We do this by or'ing in the value of
  683.      * the current window invalid mask, since it's been set to point to
  684.      * this window we must save.
  685.      */
  686.     MACH_GET_CUR_STATE_PTR(%g3, %g4)    /* puts machStatePtr in %g3 */
  687.     sethi    %hi(_machCurStatePtr), %g4
  688.                         /* update it */
  689.     st    %g3, [%g4 + %lo(_machCurStatePtr)]
  690.     add    %g3, MACH_SAVED_MASK_OFFSET, %g3
  691.     ld    [%g3], %g3
  692.     mov    %wim, %g4
  693.     or    %g3, %g4, %g4
  694.     sethi    %hi(_machCurStatePtr), %g3
  695.     ld    [%g3 + %lo(_machCurStatePtr)], %g3
  696.     add    %g3, MACH_SAVED_MASK_OFFSET, %g3
  697.     st    %g4, [%g3]
  698.  
  699.     /*
  700.      * Get and set the special handling flag in the current process state.
  701.      */
  702.     MACH_GET_CUR_PROC_PTR(%g3)
  703.     sethi    %hi(_machSpecialHandlingOffset), %g4
  704.     ld    [%g4 + %lo(_machSpecialHandlingOffset)], %g4
  705.     add    %g3, %g4, %g3
  706.     mov    0x1, %g4
  707.     st    %g4, [%g3]
  708.  
  709.     /*
  710.      * Save the current user stack pointer for this window.
  711.      */
  712.     sethi    %hi(_machCurStatePtr), %g3
  713.     ld    [%g3 + %lo(_machCurStatePtr)], %g3
  714.     add    %g3, MACH_SAVED_SPS_OFFSET, %g3
  715.     mov    %psr, %g4
  716.     and    %g4, MACH_CWP_BITS, %g4
  717.     /* Multiply by 4 bytes per int */
  718.     sll    %g4, 2, %g4
  719.     add    %g3, %g4, %g3
  720.     st    %sp, [%g3]
  721.  
  722.     /*
  723.      * Now save to internal buffer.
  724.      */
  725.     sethi    %hi(_machCurStatePtr), %g3
  726.     ld    [%g3 + %lo(_machCurStatePtr)], %g3
  727.     add    %g3, MACH_SAVED_REGS_OFFSET, %g3
  728.     /*
  729.      * Current window * 4 bytes per reg is still in %g4.  Now we just
  730.      * need to multiply it by the number of registers per window.
  731.      */
  732.     sll    %g4, MACH_NUM_REG_SHIFT, %g4
  733.     add    %g3, %g4, %g3        /* offset to start saving at */
  734.     MACH_SAVE_WINDOW_TO_BUFFER(%g3)
  735.     set    ReturnFromOverflow, %g3
  736.     jmp    %g3
  737.     nop
  738. NormalOverflow:
  739.     /*
  740.      * Save this window to stack - save locals and ins to top 16 words
  741.      * on the stack. (Since our stack grows down, the top word is %sp
  742.      * and the bottom will be (%sp + offset).
  743.      */
  744.     MACH_SAVE_WINDOW_TO_STACK()
  745. ReturnFromOverflow:
  746.     restore                /* move back to trap window */
  747.     mov    %VOL_TEMP1, %g3        /* restore global registers */
  748.     mov    %VOL_TEMP2, %g4
  749.  
  750.     /*
  751.      * jump to calling routine - this may be a trap-handler or not.
  752.      */
  753.     jmp    %SAFE_TEMP + 8
  754.     nop
  755.  
  756. /*
  757.  * ----------------------------------------------------------------------
  758.  *
  759.  * MachHandleWindowUnderflowTrap --
  760.  *
  761.  *    Trap entrance to the window underflow handler.  This sets up a
  762.  *    return address, retreats a window, calls the underflow handler,
  763.  *    advances back to window in which we entered the routine, restores
  764.  *    the psr, and returns from the trap.  We must retreat a window since
  765.  *    on a trap we are 2 windows away from the window to restore, but
  766.  *    on returning from a trap and checking if we need to restore a window,
  767.  *    we are only one window away.  See the comments in MachWindowUnderflow()
  768.  *    for more details.
  769.  *    Because we must do some work in the window we were executing in when
  770.  *    we took a trap, we must make sure to save and restore the registers
  771.  *    we use there.  This means clearing two globals out for this purpose.
  772.  *    We save and restore the globals in the actual trap window, since we
  773.  *    know we can use the local registers there freely.  The underflow
  774.  *    routine expects its return address in %RETURN_ADDR_REG, so this is the
  775.  *    register we must save and restore in the inbetween window.
  776.  *
  777.  *    In the case where the window we're restoring is for a user process,
  778.  *    we must also check for whether the stack is resident and writable.
  779.  *    If it isn't, we must page it in.  To do this is gross.  Since the
  780.  *    trap window we've entered into is 2 windows away from the window to
  781.  *    restore, we must move back one window and check the %fp there.  (This
  782.  *    will be the %sp in the actual window to restore.)  If it isn't
  783.  *    resident, then we must move forward again to the trap window and call
  784.  *    MachTrap to save state for us. Then we can call the Vm_PageIn code
  785.  *    from the trap window to page in the nasty stuff.  If it fails, we
  786.  *    must kill the user process.  All of this is complicated a bit further
  787.  *    by the fact that we have 2 addresses to test: the %fp and the
  788.  *    %fp + the size of the saved window stuff. So we check both for
  789.  *    residence.  If both are okay, we just do normal underflow.  If one or
  790.  *    the other fails, we save state.  We then test the first address,
  791.  *    if it fails, we page it in.  Then if the second one fails, we also
  792.  *    page it in.  It most likely will have been paged in by the first one,
  793.  *    though.  Then, after all this, we call the normal underflow which
  794.  *    should then be protected from page faults.  It has to be, since
  795.  *    it operates in one window back from the trap window where we saved
  796.  *    state, and we can't have any calls to Vm code there overwriting our
  797.  *    saved state.  Then we return.  If we marked that we had to save
  798.  *    state, then we must restore state by calling MachReturnFromTrap and
  799.  *    leaving as if this had all been a slow trap instead.  Unfortunately,
  800.  *    we must test some stuff twice, since there are no registers to save
  801.  *    anything into (%VOL_TEMP registers are blasted by the MachTrap code,
  802.  *    and the SAFE_TEMP register is already used to mark whether we saved
  803.  *    state).
  804.  *
  805.  *    NOTE:  In the case where we must save state by calling MachTrap,
  806.  *    a lot of the underflow code is duplicated in MachReturnFromTrap,
  807.  *    which we also end up calling.  The reason I cannot simply call
  808.  *    MachReturnFrom trap then to do all that work, is that I must do the
  809.  *    work in one window away in the case of a real underflow trap.  There
  810.  *    may be a way to deal with this, but I haven't done it yet.
  811.  *
  812.  * Results:
  813.  *    None.
  814.  *
  815.  * Side effects:
  816.  *    The window in question is restored.
  817.  *
  818.  * ----------------------------------------------------------------------
  819.  */
  820. .global    MachHandleWindowUnderflowTrap
  821. MachHandleWindowUnderflowTrap:
  822.     /*
  823.      * We need a global to mark further actions, and a global to save
  824.      * the fp in if we find it needs to be page faulted.  We can save one
  825.      * global in SAFE_TEMP since it's only whacked by MachTrap, which is
  826.      * the only thing that might whack it, in case MachTrap gets an
  827.      * overflow.  But we won't get one since this is an underflow trap.
  828.      * %o5 also appears to be safe here since it is not overwritten
  829.      * by parameters to Vm_PageIn, etc.  We also need 2 more globals for
  830.      * checking whether the stack will cause a fault.  We use a few more
  831.      * out registers that we hope Vm_PageIn won't trash. NOTE:  WE ARE
  832.      * MAKING AN ASSUMPTION that Vm_PageIn isn't compiled to mess with its
  833.      * in registers.  If we switch compilers, this may break!!!
  834.      */
  835.     mov    %g3, %SAFE_TEMP
  836.     mov    %g4, %o5
  837.     mov    %g2, %o3
  838.     mov    %g5, %o4
  839.  
  840.     /* Test if we came from user mode. */
  841.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  842.     bne    NormalUnderflow
  843.     nop
  844.  
  845.     /*
  846.      * Test if stack is resident for window we need to restore.
  847.      * This means move back a window and test its frame pointer since
  848.      * we've trapped into a window 2 away from the one whose stack is
  849.      * in question.
  850.      */
  851.     restore
  852.     /*
  853.      * If the alignment of the user stack pointer is bad, kill the process!
  854.      * We must be back in the trap window to do that.
  855.      */
  856.     andcc    %fp, 0x7, %g0
  857.     be,a    CheckForFaults
  858.     clr    %g3            /* g3 clear for no problem yet */
  859.     mov    0x1, %g3        /* Mark why we will save state */
  860.     bne,a    MustSaveState
  861.     save        /* back to trap window, in annulled delay slot */
  862.  
  863. CheckForFaults:
  864.     /*
  865.      * %g3 will have have a record of what faults would occur.
  866.      */
  867.     MACH_CHECK_STACK_FAULT(%fp, %g2, %g3, %g5, UndflFault1, UndflFault2)
  868.     mov    %fp, %g4        /* in case we need to fault it */
  869.     be    NormalUnderflow
  870.     save                /* back to trap window */
  871.  
  872. MustSaveState:
  873.     /*
  874.      * We need to save state.   We must do this in actual trap window.
  875.      * This state-saving enables traps.  We will return to
  876.      * MachReturnToUnderflowWithSavedState
  877.      */
  878.     call    _MachTrap
  879.     nop
  880. MachReturnToUnderflowWithSavedState:
  881.     /*
  882.      * We had to save state for some reason.  %g3 contains the reason
  883.      * why.
  884.      */
  885.     cmp    %g3, 0x1
  886.     be    KillTheProc
  887.     nop
  888.     andcc    %g3, 0x2, %g0
  889.     be    CheckNextUnderflow    /* It wasn't first possible fault */
  890.     nop
  891.  
  892.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  893.     /* Address that would fault is in %g4. */
  894.     mov    %g4, %o0
  895.     clr    %o1            /* also check protection???? */
  896.     call    _Vm_PageIn, 2
  897.     nop
  898.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  899.     tst    %RETURN_VAL_REG
  900.     be    CheckNextUnderflow        /* succeeded, try next */
  901.     nop
  902.     /* Otherwise, bad return, fall through to kill process. */
  903. KillTheProc:
  904.     /* Need I restore all the global registers here since it's dying? */
  905.  
  906.     mov    %SAFE_TEMP, %g3            /* restore g3 */
  907.     mov    %o5, %g4            /* restore g4 */
  908.     mov    %o3, %g2            /* etc */
  909.     mov    %o4, %g5
  910.  
  911.     /* KILL IT - must be in trap window */
  912.     MACH_SR_HIGHPRIO()    /* traps back on for overflow from printf */
  913.     set    _MachHandleWindowUnderflowDeathString, %o0
  914.     call    _printf, 1
  915.     nop
  916.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  917.     sethi    %hi(_machGenFlagsOffset), %o1
  918.     ld    [%o1 + %lo(_machGenFlagsOffset)], %o1
  919.     add    %o0, %o1, %o1
  920.     ld    [%o1], %o1
  921.     sethi    %hi(_machForeignFlag), %o2
  922.     ld    [%o2 + %lo(_machForeignFlag)], %o2
  923.     andcc    %o1, %o2, %o1            /* Is this a migrated proc? */
  924.     be    SuspendIt
  925.     nop
  926.     set    PROC_TERM_DESTROYED, %o0    /* If so, kill it. */
  927.     set    PROC_BAD_STACK, %o1
  928.     clr    %o2
  929.     call    _Proc_ExitInt, 3
  930.     nop
  931. SuspendIt:                    /* Else, make it debuggable. */
  932.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  933.     call    _Sig_CheckForKill, 1        /* kill proc if KILL signal */
  934.     nop
  935.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  936.     set    TRUE, %o1            /* debug TRUE */
  937.     set    PROC_TERM_DESTROYED, %o2
  938.     set    PROC_BAD_STACK, %o3
  939.     clr    %o4
  940.     call    _Proc_SuspendProcess, 5
  941.     nop
  942.     ba    SuspendIt        /* proc should loop if continued */
  943.     nop
  944.  
  945. CheckNextUnderflow:
  946.     andcc    %g3, 0x4, %g0        /* See if second address would fault */
  947.     be    BackAgain
  948.     nop
  949.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  950.     /* old %fp is in %g4 */
  951.     add    %g4, (MACH_SAVED_WINDOW_SIZE - 4), %o0
  952.     clr    %o1            /* also check protection???? */
  953.     call    _Vm_PageIn, 2
  954.     nop
  955.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  956.     tst    %RETURN_VAL_REG
  957.     bne    KillTheProc
  958.     nop
  959. BackAgain:
  960.     /*
  961.      * Don't deal with underflow itself.  Just pretend this was only
  962.      * a stack page fault.  User's restore instruction will get
  963.      * re-executed and will cause a further underflow trap.  This time,
  964.      * the page should be there.
  965.      */
  966.  
  967.     /* Restore globals */
  968.     mov    %SAFE_TEMP, %g3            /* restore g3 and g4 */
  969.     mov    %o5, %g4
  970.     mov    %o3, %g2
  971.     mov    %o4, %g5
  972.  
  973.     call    _MachReturnFromTrap
  974.     nop
  975.  
  976. NormalUnderflow:
  977.     restore                    /* retreat a window */
  978.     /*
  979.      * We need to preserve l6 and l7 in this window
  980.      */
  981.     mov    %l6, %g2
  982.     mov    %l7, %g5
  983.     mov    %RETURN_ADDR_REG, %g3        /* save reg in global */
  984.     set    MachWindowUnderflow, %g4    /* put address in global */
  985.     jmpl    %g4, %RETURN_ADDR_REG        /* our return addr to reg */
  986.     nop
  987.     mov    %g3, %RETURN_ADDR_REG        /* restore ret_addr */
  988.     mov    %g2, %l6
  989.     mov    %g5, %l7
  990.     save                    /* back to trap window */
  991.  
  992.     /* Restore globals */
  993.     mov    %SAFE_TEMP, %g3            /* restore g3, g4, g2 & g5 */
  994.     mov    %o5, %g4
  995.     mov    %o3, %g2
  996.     mov    %o4, %g5
  997.  
  998.     MACH_RESTORE_PSR()            /* restore psr */
  999.     jmp    %CUR_PC_REG            /* return from trap */
  1000.     rett    %NEXT_PC_REG
  1001.     nop
  1002.  
  1003.  
  1004. /*
  1005.  * ----------------------------------------------------------------------
  1006.  *
  1007.  * MachWindowUnderflow --
  1008.  *
  1009.  *    Window underflow handler.  It's set up so that it can be called as a
  1010.  *    result of a window underflow trap or as a result of needing to restore
  1011.  *    an invalid window before returning from a trap or interrupt.
  1012.  *    The address of the calling instruction is stored in %RETURN_ADDR_REG,
  1013.  *    which is the normal place.
  1014.  *
  1015.  *    The window we are in when we enter is one beyond the invalid window we
  1016.  *    need to restore. On an underflow trap we enter the kernel 2 windows
  1017.  *    away from the window that is invalid.  (This is because we tried to
  1018.  *    retreat to an invalid window and couldn't, so we trapped.  Trapping
  1019.  *    advances the current window, so we are 2 windows away from the invalid
  1020.  *    window.)  From the trap handler, then, we must retreat one window
  1021.  *    before calling this routine so that we're only one window away from
  1022.  *    the invalid window.  Then after returning from here, we must do a
  1023.  *    save to get back to our old trap window.
  1024.  *
  1025.  *    First we mark the window behind the invalid window as the
  1026.  *    new invalid window, and then we move to the invalid window.  Then we
  1027.  *    restore data from the stack into the invalid window.  Then we return
  1028.  *    to our previous window.  Note that we first mark
  1029.  *    the new invalid window and then move to the old invalid window.  If
  1030.  *    we did this in the other order, we'd get another window underflow trap.
  1031.  *    (This is the opposite order from window overflow.)
  1032.  *
  1033.  *    For the window to restore, the %sp should be good since it doesn't
  1034.  *    get changed by these routines, even if it was a user window and this
  1035.  *    is a kernel window.
  1036.  *
  1037.  *    The %sp should point to highest (on stack, lowest in memory)
  1038.  *    usable word in the current stack frame.  %fp is the %sp of the
  1039.  *    caller's stack frame, so the first (highest in memory) usable word
  1040.  *    of a current stack frame is (%fp - 4).
  1041.  *
  1042.  * Results:
  1043.  *    None.
  1044.  *
  1045.  * Side effects:
  1046.  *    The window invalid mask changes and a register window is restored.
  1047.  *
  1048.  * ----------------------------------------------------------------------
  1049.  */
  1050. .global    MachWindowUnderflow
  1051. MachWindowUnderflow:
  1052.     /*
  1053.      * Check to see if we're about to return to the trap window from
  1054.      * the debugger.  If so, then the frame pointer should be equal
  1055.      * to the base of the debugger stack.  If it is, change it to be
  1056.      * the top of the regular stack, so that when we return to the previous
  1057.      * window, our sp is at the top of the regular stack.
  1058.      * NOTE: The test below must agree with the amount we bump up the stack
  1059.      * by in MachTrap.
  1060.      */
  1061.     sethi    %hi(_machDebugStackStart), %VOL_TEMP1
  1062.                             /* base of stack */
  1063.     ld    [%VOL_TEMP1 + %lo(_machDebugStackStart)], %VOL_TEMP1
  1064.     set    MACH_FULL_STACK_FRAME, %VOL_TEMP2
  1065.     sub    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1    /* offset from base */
  1066.     cmp    %VOL_TEMP1, %fp
  1067.     bne    RegularStack
  1068.     nop
  1069.  
  1070. DealWithDebugStack:
  1071.     /* Set stack pointer of next window to regular frame pointer */
  1072.     sethi    %hi(_machSavedRegisterState), %VOL_TEMP1
  1073.     ld    [%VOL_TEMP1 + %lo(_machSavedRegisterState)], %fp
  1074.     
  1075. RegularStack:
  1076.     /*
  1077.      * We assume that by the time we've gotten here, the stack has been
  1078.      * made resident, if it was a user stack, and we can just go blasting
  1079.      * ahead.
  1080.      *
  1081.      * It should be ok to use locals here - it's a dead window.
  1082.      * Note that this means one cannot do a restore and then a save
  1083.      * and expect that the old locals in the dead window are still the
  1084.      * same.  That would be a really dumb thing to think anyway.
  1085.      */
  1086.     /* mark new invalid window */
  1087.     MACH_RETREAT_WIM(%VOL_TEMP1, %VOL_TEMP2)
  1088.  
  1089.     /* move to window to restore */
  1090.     restore
  1091.     /* restore data from stack to window - stack had better be resident! */
  1092.     MACH_RESTORE_WINDOW_FROM_STACK()
  1093.     /* Move back to previous window.   Clear registers too??? */
  1094.     save
  1095.     /*
  1096.      * jump to calling routine - this may be a trap-handler or not.
  1097.      */
  1098.     jmp    %RETURN_ADDR_REG + 8
  1099.     nop
  1100.  
  1101.  
  1102.  
  1103. /*
  1104.  * ----------------------------------------------------------------------
  1105.  *
  1106.  * MachHandleDebugTrap --
  1107.  *
  1108.  *    Enter the debugger.  This means make sure all the windows are
  1109.  *    saved to the stack, save my stack pointer, switch the stack pointer
  1110.  *    to the debugger stack, and go.
  1111.  *
  1112.  *    When we return, we change stack pointers and go to the usual
  1113.  *    return from trap routine.
  1114.  *
  1115.  * Results:
  1116.  *    None.
  1117.  *
  1118.  * Side effects:
  1119.  *    None.
  1120.  *
  1121.  * ----------------------------------------------------------------------
  1122.  */
  1123. .global    _MachHandleDebugTrap
  1124. _MachHandleDebugTrap:
  1125.     /*
  1126.      * If we came from user mode, we do different stuff.
  1127.      */
  1128.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0         /* previous state? */
  1129.         bne    KernelDebug                 /* was kernel mode */
  1130.     nop
  1131.     call    _MachUserDebug
  1132.     nop
  1133.     set    _MachReturnFromTrap, %VOL_TEMP1
  1134.     jmp    %VOL_TEMP1
  1135.     nop
  1136. KernelDebug:
  1137.     /*
  1138.      * This points to the top stack frame, which consists of a
  1139.      * Mach_RegState structure.  This is handed to the debugger.  We
  1140.      * also use this to restore our stack pointer upon returning from the
  1141.      * debugger.
  1142.      */
  1143.     sethi    %hi(_machSavedRegisterState), %VOL_TEMP1
  1144.     st    %sp, [%VOL_TEMP1 + %lo(_machSavedRegisterState)]
  1145.     /*
  1146.      * Now make sure all windows are flushed to the stack.  We do this
  1147.      * with MACH_NUM_WINDOWS - 1 saves and restores.  The window overflow
  1148.      * and underflow traps will then handle this for us.  We put the counter
  1149.      * in a global, since they have all been saved already and are free
  1150.      * for our use and we need the value across windows.
  1151.      */
  1152.  
  1153.     sethi    %hi(_machNumWindows), %g2
  1154.     ld    [%g2 + %lo(_machNumWindows)], %g2
  1155.     sub    %g2, 1, %g1
  1156. SaveSomeMore:
  1157.     save
  1158.     subcc    %g1, 1, %g1
  1159.     bne    SaveSomeMore
  1160.     nop
  1161.     sub    %g2, 1, %g1
  1162. RestoreSomeMore:
  1163.     restore
  1164.     subcc    %g1, 1, %g1
  1165.     bne    RestoreSomeMore
  1166.     nop
  1167.  
  1168.     /* Set stack base for debugger */
  1169.     sethi    %hi(_machDebugStackStart), %VOL_TEMP1
  1170.                             /* stack base */
  1171.     ld    [%VOL_TEMP1 + %lo(_machDebugStackStart)], %VOL_TEMP1
  1172.     set    MACH_FULL_STACK_FRAME, %VOL_TEMP2
  1173.     sub    %VOL_TEMP1, %VOL_TEMP2, %sp        /* offset from base */
  1174.     /* get trap type into o0 from local saved value */
  1175.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %o0
  1176.     srl    %o0, 4, %o0
  1177.     /* put saved reg ptr into o1 */
  1178.     sethi    %hi(_machSavedRegisterState), %VOL_TEMP1
  1179.     ld    [%VOL_TEMP1 + %lo(_machSavedRegisterState)], %o1
  1180.     /*
  1181.      * Set wim to this window, so that when we return from debugger,
  1182.      * we'll restore the registers for this window from the stack state
  1183.      * handled by the debugger.  This is safe to do before calling the
  1184.      * debugger, since we just saved all the windows to the stack.
  1185.      */
  1186.     MACH_SET_WIM_TO_CWP()
  1187.     /*
  1188.      * Is there a window of vulnerability here when the sp doesn't match
  1189.      * what's saved on the stack and I might restore incorrectly from
  1190.      * stack if I took another trap?  But interrupts should be off and
  1191.      * I shouldn't get a trap.
  1192.      */
  1193.  
  1194.     /* call debugger */
  1195.     call    _Dbg_Main,2
  1196.     nop
  1197.  
  1198.     /* put saved stack pointer into %sp. */
  1199.     sethi    %hi(_machSavedRegisterState), %VOL_TEMP1
  1200.     ld    [%VOL_TEMP1 + %lo(_machSavedRegisterState)], %sp
  1201.  
  1202.     /* finish as for regular trap */
  1203.     set    _MachReturnFromTrap, %VOL_TEMP1
  1204.     jmp    %VOL_TEMP1
  1205.     nop
  1206.  
  1207.  
  1208. /*
  1209.  * ----------------------------------------------------------------------
  1210.  *
  1211.  * MachSyscallTrap --
  1212.  *
  1213.  *    This is the code to handle system call traps.  The number of the
  1214.  *    system call is in %g1.
  1215.  *
  1216.  * Results:
  1217.  *    Returns a status to the caller in the caller's %o0 (or %i0).
  1218.  *
  1219.  * Side effects:
  1220.  *    Depends on the kernel call.
  1221.  *
  1222.  * ----------------------------------------------------------------------
  1223.  */
  1224. .global    MachSyscallTrap
  1225. MachSyscallTrap:
  1226.     /*
  1227.      * So that we don't re-execute the trap instruction when we
  1228.      * return from the system call trap via the return trap procedure,
  1229.      * we increment the return pc and npc here.
  1230.      */
  1231.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1232.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1233.     /*
  1234.      * Make sure user stack pointer is written into state structure so that
  1235.      * it can be used while processing the system call.  (Who uses it??)
  1236.      * This means saving the frame pointer (previous user stack pointer).
  1237.      */
  1238.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1239.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  1240.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1241.     add    %VOL_TEMP1, MACH_FP_OFFSET, %VOL_TEMP1
  1242.     st    %fp, [%VOL_TEMP1]
  1243.     /* If fork call, save registers and invalidate trapRegs stuff????? */
  1244.     /*
  1245.      * Check number of kernel call for validity.  This was stored in %g1.
  1246.      * We must be careful not to have trashed it.  But if we end up
  1247.      * trashing it, we could instead pull it out of the saved globals state
  1248.      * in the mach state structure since it got saved there.
  1249.      */
  1250.     set    _machMaxSysCall, %VOL_TEMP1
  1251.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1252.     cmp    %VOL_TEMP1, %g1
  1253.     bgeu    GoodSysCall
  1254.     nop
  1255.     /*
  1256.      * If bad, (take user error? - on spur) then do normal return from trap.
  1257.      * Is this magic number a return value?  It's in the sun3 code.
  1258.      */
  1259.     set    SYS_INVALID_SYSTEM_CALL, %RETURN_VAL_REG
  1260.     set    ReturnFromSyscall, %VOL_TEMP1
  1261.     jmp    %VOL_TEMP1
  1262.     nop
  1263. GoodSysCall:
  1264.     /*
  1265.      * Save sys call number into lastSysCall field in process state so
  1266.      * that migration can figure out what it was supposed to be.
  1267.      * %g1 must still contain syscall number.
  1268.      */
  1269.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1270.     set    _machLastSysCallOffset, %VOL_TEMP2
  1271.     ld    [%VOL_TEMP2], %VOL_TEMP2
  1272.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1273.     st    %g1, [%VOL_TEMP1]
  1274.     /*
  1275.      * Fetch args.  Copy them from user space if they aren't all in
  1276.      * the input registers.  For now I copy all the input registers,
  1277.      * since there isn't a table giving the actual number of args?
  1278.      * For args beyond the number of words that can fit in the input
  1279.      * registers, I get the offset to copy to and the pc to jump to inside
  1280.      * the copying from tables set up in Mach_SyscallInit.  If there
  1281.      * are no args to copy, then the pc gets set to jump to
  1282.      * MachFetchArgsEnd.
  1283.      */
  1284.     mov    %i5, %o5
  1285.     mov    %i4, %o4
  1286.     mov    %i3, %o3
  1287.     mov    %i2, %o2
  1288.     mov    %i1, %o1
  1289.     mov    %i0, %o0
  1290.     /*
  1291.      * Fetch offsets to copy from and to out of table.
  1292.      */
  1293.     sll    %g1, 2, %g1                /* system call index */
  1294.     set    _machArgOffsets, %VOL_TEMP2        /* offset in table */
  1295.     add    %g1, %VOL_TEMP2, %VOL_TEMP2        /* addr in table */
  1296.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset value */
  1297.     add    %fp, %VOL_TEMP2, %VOL_TEMP1        /* need global here? */
  1298.     add    %sp, %VOL_TEMP2, %VOL_TEMP2        /* need global here? */
  1299.  
  1300.     /*
  1301.      * Fetch pc branch address out of table and put it into %SAFE_TEMP
  1302.      */
  1303.     set    _machArgDispatch, %SAFE_TEMP
  1304.     add    %g1, %SAFE_TEMP, %SAFE_TEMP
  1305.     ld    [%SAFE_TEMP], %SAFE_TEMP
  1306.     jmp    %SAFE_TEMP
  1307.     nop
  1308.  
  1309. .global    _MachFetchArgs
  1310. _MachFetchArgs:
  1311.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* first word - pc offset 0 */
  1312.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1313.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1314.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1315.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* second word - pc offset 16 */
  1316.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1317.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1318.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1319.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* third word - pc offset 32 */
  1320.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1321.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1322.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1323.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* fourth word */
  1324.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1325.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1326.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1327.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* fifth word */
  1328.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1329.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1330.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1331.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* sixth word */
  1332.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1333.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1334.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1335.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* seventh word */
  1336.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1337.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1338.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1339.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* eighth word */
  1340.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1341.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1342.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1343.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* ninth word */
  1344.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1345.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1346.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1347.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* tenth word */
  1348.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1349.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1350.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1351.     /*
  1352.      * Marks last place where PC could be when a page fault occurs while
  1353.      * fetching arguments.  Needed to distinguish between a page fault
  1354.      * during arg fetch (which is okay) from other page faults in the
  1355.      * kernel, which are fatal errors.
  1356.      */
  1357. .global    _MachFetchArgsEnd
  1358. _MachFetchArgsEnd:
  1359.     /* get address from table */
  1360.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)        /* into %VOL_TEMP1 */
  1361.     set    _machKcallTableOffset, %VOL_TEMP2
  1362.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset to kcalls */
  1363.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1364.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* addr of array */
  1365.     add    %g1, %VOL_TEMP1, %VOL_TEMP1        /* index to kcall */
  1366.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* got addr */
  1367.     /* enable interrupts */
  1368.     QUICK_ENABLE_INTR(%VOL_TEMP2)
  1369.     /* go do it */
  1370.     call    %VOL_TEMP1
  1371.     nop
  1372. ReturnFromSyscall:
  1373.     /* Disable interrupts. */
  1374.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1375.     /*
  1376.      * Move return value to caller's return val register.
  1377.      */
  1378.     mov    %RETURN_VAL_REG, %RETURN_VAL_REG_CHILD
  1379.     /*
  1380.      * Sun3 checks special handling flag here.  I do it in return from
  1381.      * trap, if we came from a user process.
  1382.      */
  1383.  
  1384.     /* restore the stack pointers? */
  1385.  
  1386.     /* do normal return from trap */
  1387.     set    _MachReturnFromTrap, %VOL_TEMP1
  1388.     jmp    %VOL_TEMP1
  1389.     nop
  1390.  
  1391. /*
  1392.  * ----------------------------------------------------------------------
  1393.  *
  1394.  * MachLinkTrap --
  1395.  *
  1396.  *    This is the code to handle a dynamic linking trap #2.
  1397.  *    Apparently we don't have to do anything.
  1398.  *
  1399.  * Results:
  1400.  *    None.
  1401.  *
  1402.  * Side effects:
  1403.  *    None.
  1404.  *
  1405.  * ----------------------------------------------------------------------
  1406.  */
  1407. .global    MachLinkTrap
  1408. MachLinkTrap:
  1409.     /*
  1410.      * So that we don't re-execute the trap instruction when we
  1411.      * return from the system call trap via the return trap procedure,
  1412.      * we increment the return pc and npc here.
  1413.      */
  1414.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1415.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1416.  
  1417.     /* do normal return from trap */
  1418.     set    _MachReturnFromTrap, %VOL_TEMP1
  1419.     jmp    %VOL_TEMP1
  1420.     nop
  1421.  
  1422. /*
  1423.  * ----------------------------------------------------------------------
  1424.  *
  1425.  * MachUnixSyscallTrap --
  1426.  *
  1427.  *    This is the code to handle unix system call traps.  The number of the
  1428.  *    system call is in %g1.
  1429.  *
  1430.  * Results:
  1431.  *    Returns a status to the caller in the caller's %o0 (or %i0).
  1432.  *
  1433.  * Side effects:
  1434.  *    Depends on the kernel call.
  1435.  *
  1436.  * ----------------------------------------------------------------------
  1437.  */
  1438. .global    MachUnixSyscallTrap
  1439. MachUnixSyscallTrap:
  1440.     /*
  1441.      * So that we don't re-execute the trap instruction when we
  1442.      * return from the system call trap via the return trap procedure,
  1443.      * we increment the return pc and npc here.
  1444.      */
  1445.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1446.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1447.     /*
  1448.      * Make sure user stack pointer is written into state structure so that
  1449.      * it can be used while processing the system call.  (Who uses it??)
  1450.      * This means saving the frame pointer (previous user stack pointer).
  1451.      */
  1452.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1453.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  1454.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1455.     add    %VOL_TEMP1, MACH_FP_OFFSET, %VOL_TEMP1
  1456.     st    %fp, [%VOL_TEMP1]
  1457.     nop
  1458.     /* If fork call, save registers and invalidate trapRegs stuff????? */
  1459.     /*
  1460.      * Check number of kernel call for validity.  This was stored in %g1.
  1461.      * We must be careful not to have trashed it.  But if we end up
  1462.      * trashing it, we could instead pull it out of the saved globals state
  1463.      * in the mach state structure since it got saved there.
  1464.      */
  1465.     set    _sysUnixNumSyscalls, %VOL_TEMP1
  1466.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1467.     cmp    %VOL_TEMP1, %g1
  1468.     bgeu    GoodUnixSysCall
  1469.     nop
  1470.     /*
  1471.      * If bad, (take user error? - on spur) then do normal return from trap.
  1472.      * Is this magic number a return value?  It's in the sun3 code.
  1473.      */
  1474.     set    -1, %RETURN_VAL_REG
  1475.     set    ReturnFromUnixSyscall, %VOL_TEMP1
  1476.     jmp    %VOL_TEMP1
  1477.     nop
  1478. GoodUnixSysCall:
  1479.     /*
  1480.      * Save sys call number into lastSysCall field in process state so
  1481.      * that migration can figure out what it was supposed to be.
  1482.      * %g1 must still contain syscall number.
  1483.      */
  1484.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1485.     set    _machLastSysCallOffset, %VOL_TEMP2
  1486.     ld    [%VOL_TEMP2], %VOL_TEMP2
  1487.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1488.     st    %g1, [%VOL_TEMP1]
  1489.     /*
  1490.      * Save i0 for call restart.
  1491.      */
  1492.     st    %i0, [%VOL_TEMP1+4]
  1493.     /*
  1494.      * Fetch args.  Copy them from user space if they aren't all in
  1495.      * the input registers.  For now I copy all the input registers,
  1496.      * since there isn't a table giving the actual number of args?
  1497.      * For args beyond the number of words that can fit in the input
  1498.      * registers, I get the offset to copy to and the pc to jump to inside
  1499.      * the copying from tables set up in Mach_SyscallInit.  If there
  1500.      * are no args to copy, then the pc gets set to jump to
  1501.      * MachFetchArgsEnd.
  1502.      */
  1503.     mov    %i5, %o5
  1504.     mov    %i4, %o4
  1505.     mov    %i3, %o3
  1506.     mov    %i2, %o2
  1507.     mov    %i1, %o1
  1508.     mov    %i0, %o0
  1509.  
  1510.     cmp    %g1, 0x8b /* Sigreturn */
  1511.     be    DoSigreturn
  1512.  
  1513.     sll    %g1, 3, %g1
  1514.     set    _sysUnixSysCallTable, %VOL_TEMP2
  1515.     add    %g1, %VOL_TEMP2, %VOL_TEMP2        /* index to kcall */
  1516.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* got addr */
  1517.     /* enable interrupts */
  1518.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1519.     /* go do it */
  1520.     call    %VOL_TEMP2
  1521.     nop
  1522. ReturnFromUnixSyscall:
  1523.     /* Disable interrupts. */
  1524.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1525.     /*
  1526.      * Move return value to caller's return val register.
  1527.      */
  1528.  
  1529.     /*
  1530.      * Check if error.
  1531.      */
  1532.     cmp    %RETURN_VAL_REG, -1
  1533.     bne    UnixOk
  1534.     nop
  1535.  
  1536.     /*
  1537.      * Get the errno from the pcb and use it as the return value.
  1538.      */
  1539.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)        /* into %VOL_TEMP1 */
  1540.     set    MACH_UNIX_ERRNO_OFFSET, %VOL_TEMP2
  1541.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1542.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1543.     mov    %VOL_TEMP1, %RETURN_VAL_REG_CHILD
  1544.  
  1545.     /*
  1546.      * Set the carry to indicate an error.
  1547.      */
  1548.     mov    %CUR_PSR_REG, %VOL_TEMP2
  1549.     set    MACH_CARRY_BIT, %VOL_TEMP1
  1550.     or    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2
  1551.     mov    %VOL_TEMP2, %CUR_PSR_REG
  1552.     set    _MachReturnFromTrap, %VOL_TEMP1
  1553.     jmp    %VOL_TEMP1
  1554.     nop
  1555.  
  1556. UnixOk:
  1557.     mov    %RETURN_VAL_REG, %RETURN_VAL_REG_CHILD
  1558.     mov    %o1, %i1
  1559.     mov    %CUR_PSR_REG, %VOL_TEMP2
  1560.     set    MACH_CARRY_BITMASK, %VOL_TEMP1
  1561.     and    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2
  1562.     mov    %VOL_TEMP2, %CUR_PSR_REG
  1563.     set    _MachReturnFromTrap, %VOL_TEMP1
  1564.     jmp    %VOL_TEMP1
  1565.     nop
  1566.  
  1567. DoSigreturn:
  1568.     /* We have to skip the errno checking */
  1569.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1570.     /* go do it */
  1571.     call    _Mach_SigreturnStub
  1572.     nop
  1573.     MACH_RESTORE_WINDOW_FROM_STACK()
  1574.     /* Disable interrupts. */
  1575.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1576.     set    _MachReturnFromTrap, %VOL_TEMP1
  1577.     jmp    %VOL_TEMP1
  1578.     nop
  1579.  
  1580.  
  1581. /*
  1582.  * ----------------------------------------------------------------------
  1583.  *
  1584.  * MachHandlePageFault --
  1585.  *
  1586.  *    An instruction or data fault has occurred.  This routine will retrieve
  1587.  *    the fault error from the bus error register and the faulting address
  1588.  *    from the address error register and will call
  1589.  *    Vm routines to handle faulting in the page.
  1590.  *
  1591.  * Results:
  1592.  *    Returns to MachReturnFromTrap rather than its caller.
  1593.  *
  1594.  * Side effects:
  1595.  *    The page that caused the fault will become valid.
  1596.  *
  1597.  * ----------------------------------------------------------------------
  1598.  */
  1599. .global MachHandlePageFault
  1600. MachHandlePageFault:
  1601. #ifdef sun4c
  1602.     /* synchronous error register value as first arg - clears it too. */
  1603.     set    VMMACH_SYNC_ERROR_REG, %o0
  1604.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1605.  
  1606.     /* synch error address register value as second arg - clears it. */
  1607.     set    VMMACH_SYNC_ERROR_ADDR_REG, %o1
  1608.     lda    [%o1] VMMACH_CONTROL_SPACE, %o1
  1609.  
  1610.     /* clear async regs as well since they latch on sync errors as well. */
  1611.     set    VMMACH_ASYNC_ERROR_REG, %VOL_TEMP1
  1612.     lda    [%VOL_TEMP1] VMMACH_CONTROL_SPACE, %g0
  1613.  
  1614.     /* async error addr reg as well, so clear it.  Very silly. */
  1615.     set    VMMACH_ASYNC_ERROR_ADDR_REG, %VOL_TEMP1
  1616.     lda    [%VOL_TEMP1] VMMACH_CONTROL_SPACE, %g0
  1617. #else
  1618.     /* bus error register value as first arg. */
  1619.     set    VMMACH_BUS_ERROR_REG, %o0
  1620.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  1621.  
  1622.     /* memory address causing the error as second arg */
  1623.     set    VMMACH_ADDR_ERROR_REG, %o1
  1624.     ld    [%o1], %o1
  1625.  
  1626.     /* Write the address register to clear it */
  1627.     set    VMMACH_ADDR_ERROR_REG, %VOL_TEMP1
  1628.     st    %o1, [%VOL_TEMP1]
  1629. #endif
  1630.     /* trap value of the psr as third arg */
  1631.     mov    %CUR_PSR_REG, %o2    
  1632.  
  1633.     /* trap value of pc as fourth argument */
  1634.     mov    %CUR_PC_REG, %o3
  1635. #ifndef sun4c
  1636.     /*
  1637.      * If the trap was on a pc access rather than a data access, the
  1638.      * memoory address register won't have frozen the correct address.
  1639.      * Just move the pc into the second argument.
  1640.      */
  1641.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %VOL_TEMP1
  1642.     cmp    %VOL_TEMP1, MACH_INSTR_ACCESS
  1643.     bne    AddressValueOkay
  1644.     nop
  1645.     mov    %CUR_PC_REG, %o1
  1646. #endif
  1647. AddressValueOkay:
  1648.     /* enable interrupts */
  1649.     /*
  1650.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1651.     */
  1652.     call    _MachPageFault, 4
  1653.     nop
  1654.     /* Disable interrupts. */
  1655.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1656.  
  1657.     set    _MachReturnFromTrap, %VOL_TEMP1
  1658.     jmp    %VOL_TEMP1
  1659.     nop
  1660.  
  1661.  
  1662. /*
  1663.  * ----------------------------------------------------------------------
  1664.  *
  1665.  * MachFlushWindowsToStackTrap --
  1666.  *
  1667.  *    A trap requesting that all our windows be flushed to the stack has
  1668.  *    occured.  Bump up our return pc, since we don't want to re-execute
  1669.  *    the trap, and then call the appropriate routine.
  1670.  *
  1671.  * Results:
  1672.  *    Returns to MachReturnFromTrap, rather than our caller.
  1673.  *
  1674.  * Side effects:
  1675.  *    Register windows will be flushed to the stack and the invalid
  1676.  *    window mask will be set to point to the window before us.
  1677.  *
  1678.  * ----------------------------------------------------------------------
  1679.  */
  1680. .global    MachFlushWindowsToStackTrap
  1681. MachFlushWindowsToStackTrap:
  1682.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1683.     add    %NEXT_PC_REG, 4, %NEXT_PC_REG
  1684.     call    _Mach_FlushWindowsToStack
  1685.     nop
  1686.     set    _MachReturnFromTrap, %VOL_TEMP1
  1687.     jmp    %VOL_TEMP1
  1688.     nop
  1689.